SoA-as-graph domain foundation for OSINT/Gotham + FMA (q2 consumer)#557
Conversation
|
Warning Review limit reached
More reviews will be available in 38 minutes and 16 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughAdds a new zero-dependency ChangesSoA-as-graph domain foundation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… (q2 consumer) "Prepare everything so q2 can render nodes/edges + family nodes + HHTL CLAM hop adjacency, neo4j-emulation" — the lance-graph half (q2 renders the pixels). The OSINT domain is the Palantir-Gotham neo4j-emulation class (OGAR classid 0x0007); FMA anatomy (0x0008) is the second instance of the SAME family-node + HHTL machinery, bones as stability anchors. Reuses, does not duplicate (consult-don't-guess via two Explore agents): - graph_render.rs ALREADY is the Neo4j/Gotham surface (GraphSnapshot / RenderNode / RenderEdge, consumer = q2 cockpit) -> projected INTO, not re-typed. - NiblePath::from_guid_prefix ALREADY is the canonical GUID->path lowering -> symbiont's hhtl_path_of collapsed onto it (third copy removed). New contract::soa_graph (zero-dep, q2-consumable): - project_snapshot(&[NodeRow], &DomainSpec) -> GraphSnapshot: projects the 32-byte head (NodeGuid + EdgeBlock) — family nodes (by u24 family), member->family + in-family (identity-low-byte) + out-of-family (family-low-byte) edges. Zero value decode. - nearest_anchor: ranks each node to its nearest stability-anchor family by NiblePath::family_hop_count (new CLAM hop metric). Anchors are HEAD families (FMA bones / OSINT key entities), never value-slab types — so the projection stays head-only (E-ANCHOR-IS-A-HEAD-FIELD-NOT-A-VALUE-TYPE), falsifiably (projection_is_head_only_zero_value_decode poisons the slab). - DomainSpec + registered OSINT_GOTHAM (0x0007) + FMA_ANATOMY (0x0008). canonical_node: NodeGuid::CLASSID_OSINT/CLASSID_FMA + ReadMode::OSINT (Cognitive/CoarseOnly, hot) + ReadMode::FMA (Compressed/CoarseOnly, cold) in BUILTIN_READ_MODES. hhtl: NiblePath::family_hop_count. Rendering deferred to the q2 session; Callcenter DataFusion/gremlin POC + OntologyRegistry ClassView labels + helix-basin-anchor (CLAM<>Louvain turbovec edge residue) are named next slices — the shipped POC is hop count. cargo test -p lance-graph-contract: 698/698 (7 new). symbiont: 12/12. clippy -D warnings clean. Board updated (LATEST_STATE, AGENT_LOG, EPIPHANIES, plan) in the same commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
0da0c9b to
610198b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0da0c9b012
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let mut by_family: HashMap<u32, Vec<(u8, NodeGuid)>> = HashMap::new(); | ||
| // family_low_byte → a family id (first seen) for out-of-family resolution | ||
| let mut family_by_low: HashMap<u8, u32> = HashMap::new(); | ||
| for row in rows { |
There was a problem hiding this comment.
Filter rows by the domain classid
When the input slice contains more than one class (this change registers OSINT and FMA on separate classids), this loop indexes every row and later labels every row with domain.name; DomainSpec::classid is never checked. Calling project_snapshot(&rows, &OSINT_GOTHAM) on a mixed SoA board will include FMA/default nodes as OSINT/Gotham and resolve family/edge links across domains, so the q2 graph can show cross-domain entities that were not requested. Filter rows by row.key.classid() == domain.classid or enforce an explicit pre-filtering contract.
Useful? React with 👍 / 👎.
| .push(((g.identity() & 0xFF) as u8, g)); | ||
| family_by_low.entry((fam & 0xFF) as u8).or_insert(fam); |
There was a problem hiding this comment.
Skip ambiguous one-byte edge targets
For any family with more than 255 members, two identities can share identity & 0xFF; likewise two u24 family ids can share the same low byte. This index stores only those low bytes and later chooses the first matching member/family, so an EdgeBlock byte can be rendered as an edge to the wrong node depending on row order instead of being skipped as unresolved. Large projections such as FMA can hit these aliases; keep a unique slot-to-row mapping or mark duplicate bytes ambiguous before resolving edges.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/lance-graph-contract/src/soa_graph.rs`:
- Around line 286-295: The `node` function in the soa_graph.rs file has 8
parameters which exceeds Clippy's default threshold of 7 parameters, causing a
CI failure. Add the `#[allow(clippy::too_many_arguments)]` attribute directly
above the `node` function definition to suppress this lint warning. Since this
is a test helper function and using a builder pattern would be unnecessary
overhead, suppressing the lint here is the appropriate solution.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a80cc554-33d2-4b8a-89a5-a1d3ad762478
📒 Files selected for processing (9)
.claude/board/AGENT_LOG.md.claude/board/EPIPHANIES.md.claude/board/LATEST_STATE.md.claude/plans/unified-soa-rubikon-integration-v1.mdcrates/lance-graph-contract/src/canonical_node.rscrates/lance-graph-contract/src/hhtl.rscrates/lance-graph-contract/src/lib.rscrates/lance-graph-contract/src/soa_graph.rscrates/symbiont/src/key_render.rs
| fn node( | ||
| domain: &DomainSpec, | ||
| heel: u16, | ||
| hip: u16, | ||
| twig: u16, | ||
| family: u32, | ||
| identity: u32, | ||
| in_fam: &[u8], | ||
| out_fam: &[u8], | ||
| ) -> NodeRow { |
There was a problem hiding this comment.
Add #[allow(clippy::too_many_arguments)] to fix the CI failure.
The pipeline fails with clippy::too-many-arguments (8 args > 7 allowed). Since this is a test helper and a builder pattern would add unnecessary complexity, suppressing the lint is appropriate.
🔧 Proposed fix
/// Build a node in a domain: `classid` from the domain, hierarchy in the HHT
/// tiers, family = basin leaf, identity = leaf. Edges optional.
+ #[allow(clippy::too_many_arguments)]
fn node(
domain: &DomainSpec,
heel: u16,🧰 Tools
🪛 GitHub Actions: Style Check / 1_clippy.txt
[error] 286-295: Clippy failed: this function has too many arguments (8/7) (clippy::too-many-arguments). cargo clippy --manifest-path crates/lance-graph-contract/Cargo.toml --lib --tests -- -D warnings failed because -D warnings turns this lint into an error.
🪛 GitHub Actions: Style Check / clippy
[error] 286-295: Clippy failed: this function has too many arguments (8/7). Error: -D clippy::too-many-arguments (implied by -D warnings). Suggested: add #[allow(clippy::too_many_arguments)] or adjust function signature.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/lance-graph-contract/src/soa_graph.rs` around lines 286 - 295, The
`node` function in the soa_graph.rs file has 8 parameters which exceeds Clippy's
default threshold of 7 parameters, causing a CI failure. Add the
`#[allow(clippy::too_many_arguments)]` attribute directly above the `node`
function definition to suppress this lint warning. Since this is a test helper
function and using a builder pattern would be unnecessary overhead, suppressing
the lint here is the appropriate solution.
Source: Pipeline failures
CI's `clippy --tests` flagged the `node(...)` test helper at 8/7 args (my pre-push gate was `clippy --lib`, which skips test code). Pack the three HHT tiers into one `hht: (u16, u16, u16)` tuple → 6 args. The NodeGuid::new(...) construction and all tuple-literal inference (u16) are byte-identical to before; pure arg repacking, test semantics unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
Follow-up to PR #557 (SoA-as-graph domain foundation) + the odoo plug-and-play activation. The activation gave odoo a manifest entry + a consumer actor + a namespace bridge but no q2 rendering. PR #557 gave OSINT/FMA a render surface but didn't register odoo. Adding `ODOO_ERP` as a third `DomainSpec` closes the gap: when odoo-rs ships, its NodeRow stream projects into the same Gotham snapshot the q2 cockpit already renders. Three additive surfaces: 1. canonical_node::NodeGuid::CLASSID_ODOO = 0x0000_0050 — third registered domain classid. Chosen to mirror the OGIT G slot (OGIT::ODOO_V1.0 = 50) so classid ↔ G is visually obvious. OSINT picked 0x0007 and FMA 0x0008 (consecutive, not tied to G); ODOO matches G because the W11 activation profile is the source of truth, and 0x0050 doesn't collide with 0x0007/0x0008. 2. canonical_node::ReadMode::ODOO = (Cognitive, CoarseOnly) — hot live- business-reasoning lifecycle. Same hot tenants as OSINT: @api.depends recompute uses the same Meta+Qualia+Fingerprint+Energy+Plasticity carve as NARS hot reasoning; gated account.move.action_post lifecycle reuses Energy + Plasticity columns; NARS truth on reconciliation outcomes fits the Meta+Qualia carve. NOT Compressed (FMA's cold-reference shape), NOT Bootstrap (empty pre-class default), NOT Full (over-materializes the hot path). Registered in BUILTIN_READ_MODES. 3. soa_graph::ODOO_ERP: DomainSpec — classid CLASSID_ODOO, name "Odoo-ERP", in_family_edge "line-of" (account.move ⇆ account.move.line), out_family_edge "references" (account.move → res.partner / account.account / etc.), member_edge "member-of", anchor_families empty (callers supply invoice / journal-entry anchors per workload). Inherits FIBO-FND family slots through lance_graph_callcenter::odoo_alignment per Seam decision 1 / Option B — no new CAM codebook family minted; the DomainSpec is rendering metadata, not a new family. Acceptance: - +2 tests: canonical_node::odoo_classid_resolves_to_its_read_mode + soa_graph::odoo_erp_projects_into_the_same_gotham_surface. Both pass. - 700/700 contract lib tests (was 698 in PR #557; +1 from each new test). - Clippy -D warnings clean (after restructuring the ReadMode::ODOO doc to avoid clippy's `doc list item without indentation` lint — `Meta + Qualia + Fingerprint` looked like a list continuation at line wrap). - Format clean (cargo fmt also picked up a couple of pre-existing comment- alignment + spacing nits in hhtl.rs + nan_projection.rs, included in the commit so the tree stays fmt-clean). The projector is unchanged. project_snapshot(rows, &ODOO_ERP) and nearest_anchor(rows, &ODOO_ERP) work the same as the OSINT/FMA cases — this is consume-don't-duplicate (E-OGAR-AR-SHAPE-REHOME guard). Board hygiene: prepended EPIPHANIES E-ODOO-GOTHAM-VIEW-IS-A-DOMAINSPEC + LATEST_STATE Current Contract Inventory ADDED entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
…iwar POC Follow-up to merged #557; rolls in both codex P1 review findings + the operator's 16-family-adapter edge model + the Callcenter slice + an aiwar OSINT POC on the real graph. soa_graph (codex P1 #1 + #2, operator model): - classid IS the class (exact): project_snapshot / nearest_anchor include only rows where classid == domain.classid — a mixed-class board can't leak one domain's nodes/edges into another's view. - 16 x 8-bit family-node adapters: the canonical EdgeBlock is read as 16 family adapters (12 in-family + 4 out-of-family), each non-zero byte -> a FAMILY node by `family & 0xFF`, collision-aware (ambiguous low byte skipped, never mis-routed). Member-by-identity resolution removed -> the >255-member aliasing dissolves (resolution is family-level only). Trade: mixin dependency for extreme render stability + flexibility (E-FAMILY-ADAPTER-EDGES-ARE-RENDER-STABLE). lance-graph-callcenter (the slice): - graph_table (query-lite): GraphSnapshot -> `nodes` + `edges` arrow MemTable TableProviders + register_graph(SessionContext). The DataFusion / SQL / Cypher->SQL path (mirrors transcode::ontology_table). - graph_gremlin (always-on, pure contract types): g(&snap).v().out()/ .in_()/.out_e(label)/.values_kind() — the Gremlin POC = SurrealQL `->edge->` traversal kernel. contract::aiwar + example (the POC the operator asked for): - AiwarClassView (entity category ⇒ family id) + aiwar_node_rows ingest the real AdaWorldAPI/aiwar-neo4j-harvest/data/aiwar_graph.json into OSINT NodeRows; project_snapshot gives a Gotham graph whose family nodes ARE the categories. Example run: 221 entities/326 edges -> 281 nodes (221 members + 60 family hubs) + 481 edges. q2 wires it to the Quadro-2 visual. Tests: contract 703 lib (+5), clippy --all-targets -D warnings clean. callcenter 10 graph tests (--features query, incl. live SQL roundtrip), default build compiles graph_gremlin; new files clippy-clean (pre-existing callcenter query-clippy debt logged TD-CALLCENTER-QUERY-CLIPPY). Board updated (LATEST_STATE, AGENT_LOG, EPIPHANIES, TECH_DEBT, plan). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
Follow-up to PR #557 (SoA-as-graph domain foundation) + the odoo plug-and-play activation. The activation gave odoo a manifest entry + a consumer actor + a namespace bridge but no q2 rendering. PR #557 gave OSINT/FMA a render surface but didn't register odoo. Adding `ODOO_ERP` as a third `DomainSpec` closes the gap: when odoo-rs ships, its NodeRow stream projects into the same Gotham snapshot the q2 cockpit already renders. Three additive surfaces: 1. canonical_node::NodeGuid::CLASSID_ODOO = 0x0000_0050 — third registered domain classid. Chosen to mirror the OGIT G slot (OGIT::ODOO_V1.0 = 50) so classid ↔ G is visually obvious. OSINT picked 0x0007 and FMA 0x0008 (consecutive, not tied to G); ODOO matches G because the W11 activation profile is the source of truth, and 0x0050 doesn't collide with 0x0007/0x0008. 2. canonical_node::ReadMode::ODOO = (Cognitive, CoarseOnly) — hot live- business-reasoning lifecycle. Same hot tenants as OSINT: @api.depends recompute uses the same Meta+Qualia+Fingerprint+Energy+Plasticity carve as NARS hot reasoning; gated account.move.action_post lifecycle reuses Energy + Plasticity columns; NARS truth on reconciliation outcomes fits the Meta+Qualia carve. NOT Compressed (FMA's cold-reference shape), NOT Bootstrap (empty pre-class default), NOT Full (over-materializes the hot path). Registered in BUILTIN_READ_MODES. 3. soa_graph::ODOO_ERP: DomainSpec — classid CLASSID_ODOO, name "Odoo-ERP", in_family_edge "line-of" (account.move ⇆ account.move.line), out_family_edge "references" (account.move → res.partner / account.account / etc.), member_edge "member-of", anchor_families empty (callers supply invoice / journal-entry anchors per workload). Inherits FIBO-FND family slots through lance_graph_callcenter::odoo_alignment per Seam decision 1 / Option B — no new CAM codebook family minted; the DomainSpec is rendering metadata, not a new family. Acceptance: - +2 tests: canonical_node::odoo_classid_resolves_to_its_read_mode + soa_graph::odoo_erp_projects_into_the_same_gotham_surface. Both pass. - 700/700 contract lib tests (was 698 in PR #557; +1 from each new test). - Clippy -D warnings clean (after restructuring the ReadMode::ODOO doc to avoid clippy's `doc list item without indentation` lint — `Meta + Qualia + Fingerprint` looked like a list continuation at line wrap). - Format clean (cargo fmt also picked up a couple of pre-existing comment- alignment + spacing nits in hhtl.rs + nan_projection.rs, included in the commit so the tree stays fmt-clean). The projector is unchanged. project_snapshot(rows, &ODOO_ERP) and nearest_anchor(rows, &ODOO_ERP) work the same as the OSINT/FMA cases — this is consume-don't-duplicate (E-OGAR-AR-SHAPE-REHOME guard). Board hygiene: prepended EPIPHANIES E-ODOO-GOTHAM-VIEW-IS-A-DOMAINSPEC + LATEST_STATE Current Contract Inventory ADDED entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
…+ canon conflict Operator asked to DO the ontology-schema migration documentation. Grounded in OGAR crates/ogar-vocab/src/lib.rs (the real codebook): it already defines CODEBOOK (domain-encoded 0xDDCC), ConceptDomain + canonical_concept_domain, source_domain_concept(project|erp), canonical_concept_id, and LabelDTO — and its own note says LabelDTO "long-term belongs in lance-graph-contract; codebook id == NodeGuid.classid low u16." Surfaces a canon CONFLICT: merged CLASSID_OSINT=0x0007 routes to OGAR's Reserved domain (OSINT is 0x07XX); CLASSID_FMA=0x0008 sits in OGAR's OCR block (FMA/anatomy is clinical → Health 0x09XX). Root cause: 0x0007 minted from the early "OSINT is 0x0007" guess before ogar-vocab's 0xDDCC layout was consulted. New .claude/plans/ogar-vocab-contract-codebook-migration-v1.md (D-OVC-1..4): host the codebook/ConceptDomain/LabelDTO in contract, classids follow 0xDDCC (mint project 0x01XX + ERP 0x02XX; realign OSINT→0x0700, FMA→Health). The per-family codebook (D-GV2-2) is the finer scope of the same idea. NO code minted/rewritten: realigning merged OSINT/FMA rewrites canon (#557/#560 + CLAUDE.md canon block) → operator sign-off required (plan §5, three decisions). INTEGRATION_PLANS prepended; ISSUES ISS-CLASSID-OGAR-DRIFT filed; AGENT_LOG updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
What
Prepares the lance-graph half of the q2 OSINT graph consumer: "the basic
domain + SoA-as-a-graph" so q2 can render nodes/edges, use family nodes, and use
HHTL CLAM hop count as adjacency in a Neo4j/Palantir-Gotham emulation.
Rendering itself is wired in the q2 session — this PR ships the structural
substrate q2 projects from.
The OSINT domain is the Gotham neo4j-emulation class (OGAR classid
0x0007);FMA anatomy (
0x0008) is the second instance of the same family-node +HHTL machinery (70k structural entities, family = body region, bones as
stability anchors). The shipped POC is plain hop count — helix-basin-anchor
(CLAM ⇄ Louvain turbovec edge residue) is a named later slice.
Reuse, not duplication (grounded via two
Exploreagents before building)graph_render.rsalready is the Neo4j/Gotham surface (GraphSnapshot/RenderNode/RenderEdge, consumer = q2 cockpit) → projected into, notre-typed.
NiblePath::from_guid_prefixalready is the canonical GUID→path lowering →symbiont's
hhtl_path_ofcollapsed onto it (third copy removed).New surface (
contract::soa_graph, zero-dep, q2-consumable)project_snapshot(&[NodeRow], &DomainSpec) -> GraphSnapshot— projects the32-byte head (
NodeGuid+EdgeBlock) into the Gotham surface: familynodes (by u24
family),member→family+ in-family (identity-low-byte) +out-of-family (family-low-byte) edges. Zero value decode.
nearest_anchor(...)— ranks each node to its nearest stability-anchor familyby the new
NiblePath::family_hop_count(CLAM tree distance,2·(16−lcp)onthe fixed-depth lowering). Anchors are head families (FMA bones / OSINT key
entities), never value-slab types.
DomainSpec(domain-agnostic data) + registeredOSINT_GOTHAM(0x0007) +FMA_ANATOMY(0x0008).Canonical registrations
NodeGuid::CLASSID_OSINT/CLASSID_FMA+ReadMode::OSINT(Cognitive/CoarseOnly, hot entity graph) +
ReadMode::FMA(Compressed/CoarseOnly, cold structural reference) in
BUILTIN_READ_MODES.NiblePath::family_hop_count(the CLAM hop adjacency metric).Why head-only matters
All graph structure (domain, family grouping, hierarchy, anchors, adjacency)
keys off the head — so the whole projection, including "FMA bones as stability
anchor", stays zero-value-decode at memory-scan speed. Falsifiable:
projection_is_head_only_zero_value_decodepoisons the value slab with0xFFand asserts the snapshot is invariant. (
E-ANCHOR-IS-A-HEAD-FIELD-NOT-A-VALUE-TYPE.)Deferred (named, not built)
OntologyRegistryClassView labels (the u16 entity-type → label layer).edge residue (the operator's "for later" enhancement; this PR is hop count).
Tests
cargo test -p lance-graph-contract— 698/698 (7 new:soa_graph×5,family_hop_count, OSINT/FMA classid resolution).cargo test --manifest-path crates/symbiont— 12/12 (hhtl_path_ofconverged onto
from_guid_prefix; its 2 semantics tests updated 12→16-nibble).cargo clippy -p lance-graph-contract --lib -- -D warnings— clean.Board updated in the same commit (LATEST_STATE, AGENT_LOG, EPIPHANIES, plan)
per the board-hygiene rule.
🤖 Generated with Claude Code
Generated by Claude Code
Summary by CodeRabbit